package com.shuda.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shuda.common.dto.PageDTO;
import com.shuda.common.dto.PageResult;
import com.shuda.common.exception.BusinessException;
import com.shuda.common.utils.SecurityUtils;
import com.shuda.system.dto.TenantDTO;
import com.shuda.system.dto.TenantQueryDTO;
import com.shuda.system.entity.TenantEntity;
import com.shuda.system.mapper.TenantMapper;
import com.shuda.system.service.TenantService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 租户服务实现类
 */
@Service
public class TenantServiceImpl extends ServiceImpl<TenantMapper, TenantEntity> implements TenantService {

    @Autowired
    private TenantMapper tenantMapper;

    @Override
    public PageResult<TenantDTO> getTenantPage(PageDTO pageDTO, TenantQueryDTO queryDTO) {
        Page<TenantEntity> page = new Page<>(pageDTO.getPageNum(), pageDTO.getPageSize());
        
        LambdaQueryWrapper<TenantEntity> wrapper = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(queryDTO.getTenantName())) {
            wrapper.like(TenantEntity::getTenantName, queryDTO.getTenantName());
        }
        
        if (StringUtils.hasText(queryDTO.getTenantCode())) {
            wrapper.eq(TenantEntity::getTenantCode, queryDTO.getTenantCode());
        }
        
        if (StringUtils.hasText(queryDTO.getContactName())) {
            wrapper.like(TenantEntity::getContactName, queryDTO.getContactName());
        }
        
        if (StringUtils.hasText(queryDTO.getContactPhone())) {
            wrapper.like(TenantEntity::getContactPhone, queryDTO.getContactPhone());
        }
        
        if (queryDTO.getStatus() != null) {
            wrapper.eq(TenantEntity::getStatus, queryDTO.getStatus());
        }
        
        if (StringUtils.hasText(queryDTO.getStartTime())) {
            wrapper.ge(TenantEntity::getCreateTime, queryDTO.getStartTime());
        }
        
        if (StringUtils.hasText(queryDTO.getEndTime())) {
            wrapper.le(TenantEntity::getCreateTime, queryDTO.getEndTime());
        }
        
        wrapper.orderByDesc(TenantEntity::getCreateTime);
        
        IPage<TenantEntity> result = tenantMapper.selectPage(page, wrapper);
        
        List<TenantDTO> dtoList = result.getRecords().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        
        return new PageResult<>(dtoList, result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    public TenantDTO getTenantById(Long id) {
        TenantEntity entity = tenantMapper.selectById(id);
        if (entity == null) {
            throw new BusinessException("租户不存在");
        }
        return convertToDTO(entity);
    }

    @Override
    @Transactional
    public Long createTenant(TenantDTO tenantDTO) {
        // 验证租户编码唯一性
        LambdaQueryWrapper<TenantEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TenantEntity::getTenantCode, tenantDTO.getTenantCode());
        if (tenantMapper.selectCount(wrapper) > 0) {
            throw new BusinessException("租户编码已存在：" + tenantDTO.getTenantCode());
        }
        
        TenantEntity entity = convertToEntity(tenantDTO);
        entity.setStatus(1); // 默认启用
        entity.setCreateBy(SecurityUtils.getCurrentUsername());
        entity.setCreateTime(LocalDateTime.now());
        entity.setUpdateBy(SecurityUtils.getCurrentUsername());
        entity.setUpdateTime(LocalDateTime.now());
        entity.setDeleted(0);
        
        tenantMapper.insert(entity);
        return entity.getId();
    }

    @Override
    @Transactional
    public void updateTenant(Long id, TenantDTO tenantDTO) {
        TenantEntity existingEntity = tenantMapper.selectById(id);
        if (existingEntity == null) {
            throw new BusinessException("租户不存在");
        }
        
        // 如果修改了租户编码，验证唯一性
        if (!existingEntity.getTenantCode().equals(tenantDTO.getTenantCode())) {
            LambdaQueryWrapper<TenantEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TenantEntity::getTenantCode, tenantDTO.getTenantCode());
            if (tenantMapper.selectCount(wrapper) > 0) {
                throw new BusinessException("租户编码已存在：" + tenantDTO.getTenantCode());
            }
        }
        
        TenantEntity entity = convertToEntity(tenantDTO);
        entity.setId(id);
        entity.setUpdateBy(SecurityUtils.getCurrentUsername());
        entity.setUpdateTime(LocalDateTime.now());
        
        tenantMapper.updateById(entity);
    }

    @Override
    @Transactional
    public void deleteTenant(Long id) {
        TenantEntity entity = tenantMapper.selectById(id);
        if (entity == null) {
            throw new BusinessException("租户不存在");
        }
        
        // 逻辑删除租户
        entity.setDeleted(1);
        entity.setUpdateBy(SecurityUtils.getCurrentUsername());
        entity.setUpdateTime(LocalDateTime.now());
        tenantMapper.updateById(entity);
    }

    @Override
    @Transactional
    public void batchDeleteTenant(List<Long> ids) {
        if (ids != null && !ids.isEmpty()) {
            for (Long id : ids) {
                deleteTenant(id);
            }
        }
    }

    @Override
    @Transactional
    public void updateTenantStatus(Long id, Integer status) {
        TenantEntity entity = tenantMapper.selectById(id);
        if (entity == null) {
            throw new BusinessException("租户不存在");
        }
        
        entity.setStatus(status);
        entity.setUpdateBy(SecurityUtils.getCurrentUsername());
        entity.setUpdateTime(LocalDateTime.now());
        tenantMapper.updateById(entity);
    }

    @Override
    public List<TenantDTO> getAllEnabledTenants() {
        LambdaQueryWrapper<TenantEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TenantEntity::getStatus, 1)
                .eq(TenantEntity::getDeleted, 0)
                .orderByDesc(TenantEntity::getCreateTime);
        
        List<TenantEntity> entities = tenantMapper.selectList(wrapper);
        return entities.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public TenantDTO getTenantByCode(String tenantCode) {
        LambdaQueryWrapper<TenantEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TenantEntity::getTenantCode, tenantCode)
                .eq(TenantEntity::getDeleted, 0);
        
        TenantEntity entity = tenantMapper.selectOne(wrapper);
        return entity != null ? convertToDTO(entity) : null;
    }

    private TenantDTO convertToDTO(TenantEntity entity) {
        TenantDTO dto = new TenantDTO();
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }

    private TenantEntity convertToEntity(TenantDTO dto) {
        TenantEntity entity = new TenantEntity();
        BeanUtils.copyProperties(dto, entity);
        return entity;
    }
}